package net.mingsoft.report_data.biz.impl.report_gen;

import com.alibaba.fastjson.JSON;
import net.mingsoft.report_data.biz.ZkDataCityOdAnalysisBiz;
import net.mingsoft.report_data.biz.impl.r.*;
import net.mingsoft.report_data.dao.ZkDataDao;
import net.mingsoft.report_data.entity.*;
import net.mingsoft.report_data.entity.vo.DateWithCountDto;
import net.mingsoft.report_data.enums.PeriodEnum;
import net.mingsoft.report_data.util.ArrayUtil;
import net.mingsoft.report_data.util.MathUtil;
import net.mingsoft.report_data.util.ReportFtlRender;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gengfa
 * @date 22/03/14
 */
@Service
public class ZkCityOdAnalysisBizImpl implements ZkDataCityOdAnalysisBiz {
    @Resource
    FreeMarkerConfigurer configurer;

    @Resource
    ZkDataDao dataDao;

    private static final String[] HAI_KOU_AREA = new String[]{"龙华区", "美兰区", "琼山区", "秀英区", "未知区"};

    private static final List<OdAreaTableHead> HEAD = new ArrayList<>();

    static {
        HEAD.add(new OdAreaTableHead().setName("秀英区").setField("xyq"));
        HEAD.add(new OdAreaTableHead().setName("龙华区").setField("lhq"));
        HEAD.add(new OdAreaTableHead().setName("美兰区").setField("mlq"));
        HEAD.add(new OdAreaTableHead().setName("琼山区").setField("qsq"));
        //HEAD.add(new OdAreaTableHead().setName("未知区").setField("wzq"));
    }


    @Override
    public String generate(PeriodEnum periodEnum) {
        Map<String, Object> map = new HashMap<>(16);

        // 指标1 通勤概况分析
        getOdAverageData(map);
        getDistanceFeatureData(map);

        // 指标2 通勤时间分布特征
        getOdPeriodFeatureData(map);
        getOdCostTimeFeatureData(map);

        // 指标3 通勤人口职住地分布
        getOdFeatureWorkHomeData(map);

        // 指标4 通勤出行方式分析
        getTravelModeData(map);

        return ReportFtlRender.render(configurer, "report/form-cstqcxfs.ftl", map);
    }

    private static final String DESC_OD_SUMMARY = "{}通勤出行量日均{}万，占出行总量的{}%，平均通勤距离{}km，平均通勤耗时{}min。";

    private static final String DESC_OD_SUMMARY_P2 = "以通勤距离度量{}市职住分离度，从{}区到{}区，职住分离度逐渐增大，{}区的平均通勤距离高达{}km，{}区的平均通勤耗时高达{}min。";

    private static final String HAI_KOU = "海口市";

    private boolean belongsHaiKouArea(String areaName) {
        for (String s : HAI_KOU_AREA) {
            if (s.equals(areaName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 平均出行数据
     */
    @Override
    public Map<String, Object> getOdAverageData(Map<String, Object> map) {
        String beginDate = (String) map.get("beginDate");
        String endDate = (String) map.get("endDate");
        List<ZkDataOdAreaAvgMetricEntity> entities = dataDao.selectIdAreaAvgData(beginDate, endDate);
        List<ZkDataOdAreaAvgMetricEntity> allDataEntities = dataDao.selectIdAreaAvgAllData(beginDate, endDate);

        int haiKouTotalUser = 0;
        int otherTotalUser = 0;
        int totalDistance = 0;
        int totalTime = 0;
        for (ZkDataOdAreaAvgMetricEntity it : allDataEntities) {
            if (belongsHaiKouArea(it.getArea())) {
                haiKouTotalUser += 1;
                totalDistance += it.getOdAvgDistance();
                totalTime += it.getOdAvgCostTime();
            } else if (!it.getArea().equals(HAI_KOU)) {
                otherTotalUser += 1;
                totalDistance += it.getOdAvgDistance();
                totalTime += it.getOdAvgCostTime();
            }
        }

        Map<String, List<OdAvgTimeAndDistanceResponse>> odAvgTimeOrDistMap = new HashMap<>();
        List<OdAvgTimeAndDistanceResponse> haiKouList = new ArrayList<>();
        List<OdAvgTimeAndDistanceResponse> otherList = new ArrayList<>();
        odAvgTimeOrDistMap.put("海口市", haiKouList);
        odAvgTimeOrDistMap.put("其它市县", otherList);
        entities.forEach(it -> {
            if (belongsHaiKouArea(it.getArea())) {
                haiKouList.add(new OdAvgTimeAndDistanceResponse()
                        .setCounty(it.getArea())
                        .setDistance(it.getOdAvgDistance())
                        .setTime(it.getOdAvgCostTime()));
            } else if (!it.getArea().equals(HAI_KOU)) {
                otherList.add(new OdAvgTimeAndDistanceResponse()
                        .setCounty(it.getArea())
                        .setDistance(it.getOdAvgDistance())
                        .setTime(it.getOdAvgCostTime()));
            }
        });

        // 通勤距离
        long haiKouTotalDistance = haiKouList.stream().mapToLong(OdAvgTimeAndDistanceResponse::getDistance).sum();
        long otherTotalDistance = otherList.stream().mapToLong(OdAvgTimeAndDistanceResponse::getDistance).sum();
        // 通勤耗时
        long haiKouTotalTime = haiKouList.stream().mapToLong(OdAvgTimeAndDistanceResponse::getTime).sum();
        long otherTotalTime = otherList.stream().mapToLong(OdAvgTimeAndDistanceResponse::getTime).sum();

        if (haiKouList.size() > 0) {
            OdAvgTimeAndDistanceResponse response0 = haiKouList.get(0);
            response0.setDesc(MessageFormatter.arrayFormat(DESC_OD_SUMMARY, new String[]{
                    HAI_KOU,
                    BigDecimal.valueOf(haiKouTotalUser).divide(new BigDecimal(7), 2, 2).toPlainString(),
                    MathUtil.getRate(haiKouTotalUser, haiKouTotalUser + otherTotalUser),
                    BigDecimal.valueOf(haiKouTotalDistance).divide(new BigDecimal(haiKouTotalUser * 1000), 2, 2).toPlainString(),
                    BigDecimal.valueOf(haiKouTotalTime).divide(new BigDecimal(haiKouTotalUser * 1000), 2, 2).toPlainString()
            }).getMessage());
        }

        if (otherList.size() > 0) {
            OdAvgTimeAndDistanceResponse response0 = otherList.get(0);
            response0.setDesc(MessageFormatter.arrayFormat(DESC_OD_SUMMARY, new String[]{
                    "其它市县",
                    BigDecimal.valueOf(otherTotalUser).divide(new BigDecimal(7), 2, 2).toPlainString(),
                    MathUtil.getRate(otherTotalUser, haiKouTotalUser + otherTotalUser),
                    BigDecimal.valueOf(otherTotalDistance).divide(new BigDecimal(otherTotalUser * 1000), 2, 2).toPlainString(),
                    BigDecimal.valueOf(otherTotalTime).divide(new BigDecimal(otherTotalUser * 1000), 2, 2).toPlainString()
            }).getMessage());
        }

        map.put("odAvgTimeOrDistMap", JSON.toJSONString(odAvgTimeOrDistMap));
        return map;
    }

    /**
     * 区域距离段特征
     */
    @Override
    public Map<String, Object> getDistanceFeatureData(Map<String, Object> map) {
        OdAreaDistanceFeatureResponse response = new OdAreaDistanceFeatureResponse();
        response.setHead(HEAD);

        List<OdAreaPeopleCountData> peopleCountData = new ArrayList<>();
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("3KM以内人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("3~5KM人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("5~15KM人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("15~30KM人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("30~50KM人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("50KM以上人数"));
        response.setData(peopleCountData);
        String beginDate = (String) map.get("beginDate");
        String endDate = (String) map.get("endDate");
        List<ZkDataOdFeatureDistanceEntity> entities = dataDao.selectOdFeatureDistanceData(beginDate, endDate);
        entities.forEach(it -> {
            if ("龙华区".equals(it.getArea())) {
                peopleCountData.get(0).setLhq(it.getD1());
                peopleCountData.get(1).setLhq(it.getD2());
                peopleCountData.get(2).setLhq(it.getD3());
                peopleCountData.get(3).setLhq(it.getD4());
                peopleCountData.get(4).setLhq(it.getD5());
                peopleCountData.get(5).setLhq(it.getD6());
            } else if ("琼山区".equals(it.getArea())) {
                peopleCountData.get(0).setQsq(it.getD1());
                peopleCountData.get(1).setQsq(it.getD2());
                peopleCountData.get(2).setQsq(it.getD3());
                peopleCountData.get(3).setQsq(it.getD4());
                peopleCountData.get(4).setQsq(it.getD5());
                peopleCountData.get(5).setQsq(it.getD6());
            } else if ("秀英区".equals(it.getArea())) {
                peopleCountData.get(0).setXyq(it.getD1());
                peopleCountData.get(1).setXyq(it.getD2());
                peopleCountData.get(2).setXyq(it.getD3());
                peopleCountData.get(3).setXyq(it.getD4());
                peopleCountData.get(4).setXyq(it.getD5());
                peopleCountData.get(5).setXyq(it.getD6());
            } else if ("美兰区".equals(it.getArea())) {
                peopleCountData.get(0).setMlq(it.getD1());
                peopleCountData.get(1).setMlq(it.getD2());
                peopleCountData.get(2).setMlq(it.getD3());
                peopleCountData.get(3).setMlq(it.getD4());
                peopleCountData.get(4).setMlq(it.getD5());
                peopleCountData.get(5).setMlq(it.getD6());
            }/* else if ("未知区".equals(it.getArea())) {
                peopleCountData.get(0).setWzq(it.getD1());
                peopleCountData.get(1).setWzq(it.getD2());
                peopleCountData.get(2).setWzq(it.getD3());
                peopleCountData.get(3).setWzq(it.getD4());
                peopleCountData.get(4).setWzq(it.getD5());
                peopleCountData.get(5).setWzq(it.getD6());
            }*/
        });
        map.put("dataTable3", JSON.toJSONString(response));
        String dataTable3LessThan3km = max(response.getData().get(0));
        String dataTable3MoreThan60km = max(response.getData().get(response.getData().size() - 1));
        map.put("dataTable3LessThan3km", dataTable3LessThan3km);
        map.put("dataTable3MoreThan60km", dataTable3MoreThan60km);
        return map;
    }

    private static final String DESC_CO_TIME = "由于工作时间的固定性，如图4，从通勤出行出发时间角度看，早{}-{}出行量持续升高，晚{}-{}出行量持续升高。早高峰时段，{}通勤出行达到最高峰{}万人次，晚高峰时段{}达到最高峰{}万人次。由此可见，早高峰通勤出行更为集中。";

    /**
     * 时间段特征数据
     */
    @Override
    public Map<String, Object> getOdPeriodFeatureData(Map<String, Object> map) {
        List<OdPeriodFeatureResponse> responses = new ArrayList<>();

        String beginDate = (String) map.get("beginDate");
        String endDate = (String) map.get("endDate");
        // 查询数据
        List<ZkDataOdFeaturePeriodEntity> entities = dataDao.selectOdFeaturePeriodData(beginDate, endDate);
        entities.forEach(it -> responses.add(new OdPeriodFeatureResponse().setTime(it.getTime()).setPeopleCount(it.getCount())));
        Map<String, List<ZkDataOdFeaturePeriodEntity>> entitiesGroupByDate = entities.stream().collect(Collectors.groupingBy(o -> o.getTime().substring(0, 10), LinkedHashMap::new, Collectors.toList()));
        entitiesGroupByDate.forEach((key, value) -> value.forEach(ev -> ev.setTime(ev.getTime().substring(11))));

        // 根据24小时合并数据，获取递增区间
        List<DateWithCountDto> mergeByTimeList = entities.stream()
                .collect(Collectors.groupingBy(ZkDataOdFeaturePeriodEntity::getTime))
                .entrySet()
                .stream()
                .map(o -> new DateWithCountDto()
                        .setCount(String.valueOf(o.getValue().stream().mapToLong(ZkDataOdFeaturePeriodEntity::getCount).sum()))
                        .setDate(o.getKey()))
                .sorted(Comparator.comparing(DateWithCountDto::getDate))
                .collect(Collectors.toList());
        List<List<Integer>> growthParts = ArrayUtil.getGrowthPart(mergeByTimeList.stream().map(o -> Long.parseLong(o.getCount())).collect(Collectors.toList()));

        map.put("dataTable4", JSON.toJSONString(entitiesGroupByDate));
        if (growthParts.size() >= 2) {
            List<Integer> part1 = growthParts.get(0);
            List<Integer> part2 = growthParts.get(growthParts.size() - 1);
            DateWithCountDto dtoA1 = mergeByTimeList.get(part1.get(0));
            DateWithCountDto dtoA2 = mergeByTimeList.get(part1.get(part1.size() - 1));
            DateWithCountDto dtoB1 = mergeByTimeList.get(part2.get(0));
            DateWithCountDto dtoB2 = mergeByTimeList.get(part2.get(part2.size() - 1));
            String desc = MessageFormatter.arrayFormat(DESC_CO_TIME, new String[]{
                    dtoA1.getDate(), dtoA2.getDate(),
                    dtoB1.getDate(), dtoB2.getDate(),
                    dtoA2.getDate(), new BigDecimal(dtoA2.getCount()).divide(new BigDecimal(70000), 2, 2).toPlainString(),
                    dtoB2.getDate(), new BigDecimal(dtoB2.getCount()).divide(new BigDecimal(70000), 2, 2).toPlainString(),
            }).getMessage();
            map.put("dataTable4GrowthDesc", desc);
        } else {
            map.put("dataTable4GrowthDesc", "");
        }
        map.put("dataTable4GrowthMap", JSON.toJSONString(growthParts));
        return map;
    }

    /**
     * 消耗时间特性数据
     */
    @Override
    public Map<String, Object> getOdCostTimeFeatureData(Map<String, Object> map) {
        OdAreaCostTimeFeatureResponse response = new OdAreaCostTimeFeatureResponse();
        response.setHead(HEAD);

        List<OdAreaPeopleCountData> peopleCountData = new ArrayList<>();
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("15min以内人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("15~30min人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("30~45min人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("45~60min人数"));
        peopleCountData.add(new OdAreaPeopleCountData().setPeopleCount("60min以上人数"));
        response.setData(peopleCountData);

        String beginDate = (String) map.get("beginDate");
        String endDate = (String) map.get("endDate");

        List<ZkDataOdFeatureCostTimeEntity> entities = dataDao.selectOdFeatureCostTimeData(beginDate, endDate);

        entities.forEach(it -> {
            if ("龙华区".equals(it.getArea())) {
                peopleCountData.get(0).setLhq(it.getC1());
                peopleCountData.get(1).setLhq(it.getC2());
                peopleCountData.get(2).setLhq(it.getC3());
                peopleCountData.get(3).setLhq(it.getC4());
                peopleCountData.get(4).setLhq(it.getC5());
            } else if ("琼山区".equals(it.getArea())) {
                peopleCountData.get(0).setQsq(it.getC1());
                peopleCountData.get(1).setQsq(it.getC2());
                peopleCountData.get(2).setQsq(it.getC3());
                peopleCountData.get(3).setQsq(it.getC4());
                peopleCountData.get(4).setQsq(it.getC5());
            } else if ("秀英区".equals(it.getArea())) {
                peopleCountData.get(0).setXyq(it.getC1());
                peopleCountData.get(1).setXyq(it.getC2());
                peopleCountData.get(2).setXyq(it.getC3());
                peopleCountData.get(3).setXyq(it.getC4());
                peopleCountData.get(4).setXyq(it.getC5());
            } else if ("美兰区".equals(it.getArea())) {
                peopleCountData.get(0).setMlq(it.getC1());
                peopleCountData.get(1).setMlq(it.getC2());
                peopleCountData.get(2).setMlq(it.getC3());
                peopleCountData.get(3).setMlq(it.getC4());
                peopleCountData.get(4).setMlq(it.getC5());
            } else if ("未知区".equals(it.getArea())) {
                peopleCountData.get(0).setWzq(it.getC1());
                peopleCountData.get(1).setWzq(it.getC2());
                peopleCountData.get(2).setWzq(it.getC3());
                peopleCountData.get(3).setWzq(it.getC4());
                peopleCountData.get(4).setWzq(it.getC5());
            }
        });

        map.put("dataTable5", JSON.toJSONString(response));
        List<OdAreaPeopleCountData> data = response.getData();
        String lessThan3kmMax = max(data.get(0));
        String lessThan3kmMin = min(data.get(0));
        String moreThan60KmMax = max(data.get(data.size() - 1));
        String moreThan60KmMin = min(data.get(data.size() - 1));
        map.put("lessThan3kmMax", lessThan3kmMax);
        map.put("lessThan3kmMin", lessThan3kmMin);
        map.put("moreThan60KmMax", moreThan60KmMax);
        map.put("moreThan60KmMin", moreThan60KmMin);
        return map;
    }

    private static final String DESC_OD_HOME_DISTRIBUTE = "据统计结果发现，居住在{}的人数最多，高达{}人，该区域对应的工作人口数量为{}人；其次是{}，居住人数为{}人，工作人数为{}人。\n ";
    private static final String DESC_OD_WORK_DISTRIBUTE = "工作在{}的人数最多，高达{}万人，该区域对应的居住人口数量为{}万人；其次是{}，工作人数为{}万人，居住人数为{}万人。";

    /**
     * 获取职住特征数据
     */
    @Override
    public Map<String, Object> getOdFeatureWorkHomeData(Map<String, Object> map) {
        List<OdFeatureWorkHomeResponse> workResponses = new ArrayList<>();
        List<OdFeatureWorkHomeResponse> homeResponse = new ArrayList<>();

        String beginDate = (String) map.get("beginDate");
        String endDate = (String) map.get("endDate");

        List<ZkDataOdPopulationWorkHomeEntity> entities = dataDao.selectOdPopulationWorkHomeData(beginDate, endDate);
        Map<String, List<ZkDataOdPopulationWorkHomeEntity>> typeMap = entities.stream().collect(Collectors.groupingBy(o -> String.valueOf(o.getType())));
        if (CollectionUtils.isNotEmpty(entities)) {
            // 工作地
            for (Map.Entry<String, List<ZkDataOdPopulationWorkHomeEntity>> it : typeMap.get("0").stream().collect(Collectors.groupingBy(ZkDataOdPopulationWorkHomeEntity::getCounty)).entrySet()) {
                workResponses.add(new OdFeatureWorkHomeResponse().setCounty(it.getKey()).setCount(it.getValue().stream().mapToLong(ZkDataOdPopulationWorkHomeEntity::getCount).sum()));
            }
            // 居住地
            for (Map.Entry<String, List<ZkDataOdPopulationWorkHomeEntity>> it : typeMap.get("1").stream().collect(Collectors.groupingBy(ZkDataOdPopulationWorkHomeEntity::getCounty)).entrySet()) {
                homeResponse.add(new OdFeatureWorkHomeResponse().setCounty(it.getKey()).setCount(it.getValue().stream().mapToLong(ZkDataOdPopulationWorkHomeEntity::getCount).sum()));
            }
        }

        Map<String, Long> homeResponseMap = homeResponse.stream().collect(Collectors.toMap(OdFeatureWorkHomeResponse::getCounty, OdFeatureWorkHomeResponse::getCount));

        homeResponse.sort(Comparator.comparing(OdFeatureWorkHomeResponse::getCount).reversed());
        workResponses.sort(Comparator.comparing(OdFeatureWorkHomeResponse::getCount).reversed());
        OdFeatureWorkHomeResponse firstObj;
        if (homeResponse.size() <= 0) {
            firstObj = new OdFeatureWorkHomeResponse();
        } else {
            firstObj = workResponses.get(0);
        }
        OdFeatureWorkHomeResponse secondObj;
        if (workResponses.size() <= 0) {
            secondObj = new OdFeatureWorkHomeResponse();
        } else {
            secondObj = workResponses.get(1);
        }

        String descP2 = "";
        if (workResponses.size() >= 2) {
            descP2 = MessageFormatter.arrayFormat(DESC_OD_WORK_DISTRIBUTE, new String[]{
                    workResponses.get(0).getCounty(),
                    MathUtil.getTenThousand(workResponses.get(0).getCount()),
                    MathUtil.getTenThousand(homeResponseMap.getOrDefault(workResponses.get(0).getCounty(), 0L)),
                    workResponses.get(1).getCounty(),
                    MathUtil.getTenThousand(workResponses.get(1).getCount()),
                    MathUtil.getTenThousand(homeResponseMap.getOrDefault(workResponses.get(1).getCounty(), 0L)),
            }).getMessage();
        }

        map.put("coWorkHomeDescP2", descP2);
        map.put("dataTable6First", JSON.toJSONString(firstObj));
        map.put("dataTable6FirstWork", JSON.toJSONString(getWhObjCount(workResponses, firstObj.getCounty())));
        map.put("dataTable6Second", JSON.toJSONString(secondObj));
        map.put("dataTable6SecondWork", JSON.toJSONString(getWhObjCount(workResponses, secondObj.getCounty())));
        map.put("dataTable6", JSON.toJSONString(homeResponse));
        map.put("dataTable7", JSON.toJSONString(workResponses));
        return map;
    }

    private long getWhObjCount(List<OdFeatureWorkHomeResponse> responses, String area) {
        for (OdFeatureWorkHomeResponse response : responses) {
            if (StringUtils.equals(response.getCounty(), area)) {
                return response.getCount();
            }
        }
        return 0;
    }

    @Override
    public Map<String, Object> getTravelModeData(Map<String, Object> map) {
        // FIXED DATA
        List<OdTravelModeResponse> responses = new ArrayList<>();
        responses.add(new OdTravelModeResponse().setTravelMode("步行").setCount("28"));
        responses.add(new OdTravelModeResponse().setTravelMode("自行车").setCount("1.6"));
        responses.add(new OdTravelModeResponse().setTravelMode("公交").setCount("9.6"));
        responses.add(new OdTravelModeResponse().setTravelMode("小汽车").setCount("21.8"));
        responses.add(new OdTravelModeResponse().setTravelMode("出租车（滴滴出行）").setCount("2.6"));
        responses.add(new OdTravelModeResponse().setTravelMode("班车").setCount("1.2"));
        responses.add(new OdTravelModeResponse().setTravelMode("电动车").setCount("34.9"));
        responses.add(new OdTravelModeResponse().setTravelMode("摩托车").setCount("0.3"));
        map.put("dataTable8", JSON.toJSONString(responses));
        return map;
    }

    private String getRate(Long a, Long b) {
        final BigDecimal aD = BigDecimal.valueOf(a);
        final BigDecimal bD = BigDecimal.valueOf(b);
        return aD.divide(bD, 4, BigDecimal.ROUND_DOWN)
                .multiply(BigDecimal.valueOf(100)).setScale(2, BigDecimal.ROUND_DOWN).toPlainString();
    }

    private String max(OdAreaPeopleCountData data) {
        Long[] dt = new Long[]{data.getLhq(), data.getMlq(), data.getQsq(), data.getXyq()};
        long max = dt[0];
        int maxIdx = 0;
        for (int i = 1; i < dt.length; i++) {
            if (dt[i] > max) {
                max = dt[i];
                maxIdx = i;
            }
        }
        return HAI_KOU_AREA[maxIdx];
    }

    private String min(OdAreaPeopleCountData data) {
        Long[] dt = new Long[]{data.getLhq(), data.getMlq(), data.getQsq(), data.getXyq()};
        long min = dt[0];
        int minIdx = 0;
        for (int i = 1; i < dt.length; i++) {
            if (dt[i] < min) {
                min = dt[i];
                minIdx = i;
            }
        }
        return HAI_KOU_AREA[minIdx];
    }
}
